import subprocess
import numpy as np
import threading
import time
import os
import signal
from collections import deque
import soundfile as sf

# 设置参数
device = "hw:1,0"
format = "S16_LE"
channels = 2
rate = 48000
buffer_duration = 10  # 缓冲区长度，单位：秒
chunk_size = int(rate / 10 * 2 * channels)  # 0.1s的数据量，每帧2字节
buffer_chunks = int(buffer_duration * rate / (chunk_size // channels))  # 计算缓冲区需要的chunk数量
single_channel_output_file = "test_single_channel.wav"

# 创建缓冲区（双端队列）
audio_buffer = deque(maxlen=buffer_chunks)

# 读写锁
lock = threading.Lock()


# 音频采集线程函数
def audio_capture():
    global running, process
    command = [
        "arecord",
        "-D", device,
        "-f", format,
        "-c", str(channels),
        "-r", str(rate),
        "-t", "raw"
    ]

    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while running:
        data = process.stdout.read(chunk_size)  # 每次读取chunk_size大小的数据
        if not data:
            break
        with lock:
            audio_buffer.append(data)

    process.stdout.close()
    process.wait()


# 启动音频采集线程
def start_audio_capture():
    global running, thread
    running = True
    thread = threading.Thread(target=audio_capture)
    thread.daemon = True
    thread.start()


# 停止音频采集线程
def stop_audio_capture():
    global running, process
    running = False
    if process:
        process.terminate()
        time.sleep(0.02)  # 短暂等待以便进程响应
        if process.poll() is None:  # 检查进程是否仍在运行
            os.kill(process.pid, signal.SIGKILL)  # 强制终止进程
        process.wait()  # 确保进程完全结束
    thread.join()


# 获取音频片段
def get_audio_segment(duration):
    samples = int(rate * duration)  # 计算需要的样本数
    channel_index = 0  # 第5通道的索引（从0开始计算）
    while True:
        with lock:
            if len(audio_buffer) * chunk_size // (channels * 2) >= samples:
                audio_data = b''.join(list(audio_buffer)[-samples // (chunk_size // (channels*2)):])
                break
        time.sleep(0.1)  # 等待更多数据到达

    # 提取第5通道的数据
    channel_data = np.frombuffer(audio_data, dtype=np.int16).reshape(-1, channels)[:, channel_index]
    return channel_data


# 定期将缓冲区数据写入文件，仅保存第5通道
def write_buffer_to_file(output_file):
    channel_index = 0  # 第5通道的索引（从0开始计算）
    with lock:
        audio_data = b''.join(audio_buffer)

    # 提取第5通道的数据
    channel_data = np.frombuffer(audio_data, dtype=np.int16).reshape(-1, channels)[:, channel_index]

    # 将数据写入.wav文件
    sf.write(output_file, channel_data, rate, 'PCM_16')


# 示例：持续采集音频，同时每隔一段时间将缓冲区数据写入文件
if __name__ == "__main__":
    # subprocess.run(["sudo", "fuser", "-v", "/dev/snd/pcmC3D0c"])
    # subprocess.run(["sudo", "fuser", "-k", "/dev/snd/pcmC3D0c"])
    try:
        start_audio_capture()
        while True:
            time.sleep(4)
            # time.sleep(3)
            # write_buffer_to_file(single_channel_output_file)
            sf.write(single_channel_output_file,get_audio_segment(4), rate, 'PCM_16')

            print(f"Captured segment written to {single_channel_output_file}")
    except KeyboardInterrupt:
        stop_audio_capture()
